  <template>
    <div id="app">
      <div>computed的值:{{ result }}</div>
      <button @click="watchObjectFn">watch监听--对象的形式</button>
      <button @click="watchFunctionFn">watch监听--方法的形式</button><hr>
      <button @click="dataFn1">监听多个数据1</button>{{ data1 }}
      <button @click="dataFn2">监听多个数据2</button>{{ data2 }}
    </div>
  </template>
  
  <script>
  export default {
    name: 'App',
    components: {
    },
    data(){
      return{
        data1:1,        //同时监听多个数据的变化
        data2:2,
        watchObject: {                //watch的监听(对象的形式)
          name: "张三",
        },
        watchFunction: "方法原数据",   //watch的监听(方法的形式)
      }
    },

    computed: {
      // 计算属性的第一种写法---对象的形式
      fullName: {
        // getter
        get: function () {
          return this.firstName + ' ' + this.lastName
        },
        // setter
        set: function (newValue) {
          var names = newValue.split(' ')
          this.firstName = names[0]
          this.lastName = names[names.length - 1]
        }
      },
//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————

      // 计算属性的第二种写法---方法的形式
      result(){
        console.log("computed支持缓存，只有依赖的数据发生变化后才会重新计算！！！");
        return this.data1 + 1
        // return setTimeout(()=>this.data1 + 100,5000)  //不支持异步操作，无法获取到数据的变化。
      },

      //这里是用于监听多个数据的变化
      changeData(){     
        var d1 = this.data1
        var d2 = this.data2
        return {d1, d2}
      }
    },
// ===============================================================================================================================
// ===============================================================================================================================
// ===============================================================================================================================
    watch: {
      // 监听器的第一种写法---对象的形式
      // 监听对象中的某个属性，选中的属性要使用双引号括起来。   
      // 如果监听整个对象，即使开了deep，也拿不到旧值
      watchObject: {
        handler(newVal, oldVal){
          console.log(newVal, oldVal);  //两个值相同，拿不到旧值
        },
        // immediate: true,
        deep: true
      },
      // "watchObject.name": {
      //   handler(newVal, oldVal){
      //     console.log(newVal, oldVal);  //李四，张三
      //   },
      // },

//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// 监听器的第二种写法---方法的形式
      // 不应该用箭头函数来定义 watcher 函数 ，因为箭头函数绑定了父级作用域的上下文，`this` 将不指向 Vue 实例，

      // watchFunction: (newVal, oldVal)=> {
      //   console.log(newVal, oldVal, this);
      // },

      changeData(newVal, oldVal){  //监听多个数据的变化：通过上面的计算属性获取到要监听的数据，然后监听这个计算属性
        console.log(newVal, oldVal);
        if(newVal.d1 != oldVal.d1 && newVal.d2 != oldVal.d2){
          console.log("监听到两个数据都发生了改变");
        }
      },

//—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// 监听器的第三种写法---数组的形式
    // 可以传入回调数组，这些方法会被逐一调用
      // watchObject: [
      //   'handle1',
      //   function handle2 (val, oldVal) { /* ... */ },
      //   {
      //     handler: function handle3 (val, oldVal) { /* ... */ },
      //     /* ... */
      //   }
      // ],      
    },
    
    mounted(){
      //这个方法在生命周期和方法中都可以使用。返回一个取消监听的函数fn
      this.$watch("this.data1", (newVal,oldVal)=>{console.log("$watch监听：数据没有变化");}, {immediate: true})
      var unwatch = this.$watch(()=>{       //同时监听多个数据
                var c = this.data1
                var d = this.data2
                return {c,d}
            }, ()=>{
              console.log("$watch监听：c和d都没有变化");
              // 如果希望在回调内部调用一个取消侦听的函数，你应该先检查其函数的可用性：
              // if (unwatch) {
              //   unwatch()
              // }
            }, {immediate: true})
    },
// ===============================================================================================================================
// ===============================================================================================================================
// ===============================================================================================================================
    methods:{
      watchObjectFn(){
        this.watchObject.name = "李四"  //如果监听对象，要使用deep监听，如果监听属性，属性要使用引号括起来
      },
      watchFunctionFn(){
        this.watchFunction = "数据改变了，监听到了吗？"
      },
      //监听多个数据的变化
      dataFn1(){
        this.data1 = 100
        this.data2 = 200
      },
      dataFn2(){
        this.data2 = 200
      }
    },
  }

  
  </script>
  
  <style scoped>
  #app {
    font-family: Avenir, Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }

  </style>
  